package com.hanthink.common.utils.file;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import io.minio.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import com.hanthink.common.config.HdfsProperties;

import io.minio.errors.ErrorResponseException;
import io.minio.errors.InsufficientDataException;
import io.minio.errors.InternalException;
import io.minio.errors.BucketPolicyTooLargeException;
import io.minio.errors.InvalidResponseException;
import io.minio.errors.XmlParserException;
import io.minio.messages.Bucket;

/**
 * <p>
 * Title: MinioUtils
 * </p>
 * <p>
 * Description: 对象存储工具类
 * </p>
 *
 * @author vondser
 * @date 2020年12月8日
 */
@Component
public class MinioUtils {

	protected final static Logger logger = LoggerFactory.getLogger(MinioUtils.class);

	@Autowired
	private HdfsProperties hdfsProperties;

	@Autowired
	private MinioClient client;

	/**
	 * 上传文件
	 */
	public String uploadFile(MultipartFile file,String bucketName) throws Exception {

		String msg = "";
		// 判断文件是否为空
		if (null == file || 0 == file.getSize()) {
			msg = "上传文件不能为空";
			return msg;
		}

		// 参数配置
		Map<String, String> headers = new HashMap<String, String>();
		headers.put("Content-Type", file.getContentType());

		// 文件名
		String originalFilename = file.getOriginalFilename();

		// 新的文件名 = 存储桶文件名_时间戳.后缀名
		String filelName = bucketName + "_" + System.currentTimeMillis()
				+ originalFilename.substring(originalFilename.lastIndexOf("."));

		InputStream inputStream = file.getInputStream();

		client.putObject(
				PutObjectArgs.builder().bucket(hdfsProperties.getBucketName()).object(filelName).stream(
								inputStream, inputStream.available(), -1)
						.build());

		File files = new File(file.getName());
		InputStream bais = new FileInputStream(files);
		client.putObject(
				PutObjectArgs.builder().bucket(hdfsProperties.getBucketName()).object(file.getName()).stream(
								bais, bais.available(), -1)
						.build());

		//msg = hdfsProperties.getEndpoint() + "/" + bucketName + "/" + filelName;
		msg =  "http://39.100.236.78:9000/" + bucketName + "/" + filelName;

		return msg;
	}

	/**
	 * 生成文件名
	 */
	public String createFileName(String fileType) throws Exception {

		// 新的文件名 = 存储桶文件名_时间戳.后缀名
		String filelName = hdfsProperties.getBucketName() + "_" + System.currentTimeMillis() + '.' + fileType;

		return filelName;
	}

	/**
	 * app上传文件
	 */
	public String appUploadFile(MultipartFile file, String fileName) throws Exception {
		String msg = "";
		// 判断文件是否为空
		if (null == file || 0 == file.getSize()) {
			msg = "上传文件不能为空";
			return msg;
		}

		// 参数配置
		Map<String, String> headers = new HashMap<String, String>();
		headers.put("Content-Type", file.getContentType());

		InputStream inputStream = file.getInputStream();


		// 参数配置
//		PutObjectOptions options = new PutObjectOptions(inputStream.available(), -1);
//		options.setHeaders(headers);
		// 开始上传
		//client.putObject(hdfsProperties.getBucketName(), fileName, inputStream, options);
		File files = new File(fileName);
		//InputStream bais = new FileInputStream(file.getInputStream());
		client.putObject(
				PutObjectArgs.builder().bucket(hdfsProperties.getBucketName()).object(fileName).stream(
								file.getInputStream(), file.getInputStream().available(), -1)
						.build());


		//msg = hdfsProperties.getEndpoint() + "/" + hdfsProperties.getBucketName() + "/" + fileName;
		msg =  "http://39.100.236.78:9000/" + hdfsProperties.getBucketName() + "/" + fileName;

		return msg;
	}

	/**
	 * 获取当前文件桶
	 *
	 * @return
	 */
	public String getCurrentBucket() {
		String bucketName = BucketNameConfig.getYearAndMonth();
		if (!bucketExists(bucketName)) {
			createBucket(bucketName);
		}
		hdfsProperties.setBucketName(bucketName);
		return bucketName;
	}

	/**
	 * 获取全部bucket
	 */
	public List<Bucket> getAllBuckets() throws Exception {
		return client.listBuckets();
	}

	/**
	 * 检查文件存储桶是否存在
	 *
	 * @param bucketName
	 * @return
	 */
	public boolean bucketExists(String bucketName) {
		try {
			return client.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	/**
	 * 创建bucket
	 *
	 * @param bucketName bucket名称
	 */
	public void createBucket(String bucketName) {
		try {
			if (!bucketExists(bucketName)) {
				client.makeBucket(
						MakeBucketArgs.builder()
								.bucket(bucketName)
								.build());

				//权限策略配置
				String config = "{\"Version\":\"2012-10-17\","
						+ "\"Statement\":[{\"Effect\":\"Allow\","
						+ "\"Principal\":{\"AWS\":[\"*\"]},"
						+ "\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucket\",\"s3:ListBucketMultipartUploads\"],"
						+ "\"Resource\":[\"arn:aws:s3:::"+bucketName+"\"]},"
						+ "{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},"
						+ "\"Action\":[\"s3:ListMultipartUploadParts\",\"s3:PutObject\",\"s3:AbortMultipartUpload\",\"s3:DeleteObject\",\"s3:GetObject\"],"
						+ "\"Resource\":[\"arn:aws:s3:::"+bucketName+"/*\"]}]}";
				client.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucketName).config(config).build());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}


//	public Optional<Bucket> getBucket()
//			throws IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException,
//			InvalidResponseException, InternalException, BucketPolicyTooLargeException, ErrorResponseException, IllegalArgumentException, XmlParserException {
//		return client.listBuckets().stream().filter(b -> b.name().equals(hdfsProperties.getBucketName())).findFirst();
//	}


	public void removeBucket() throws Exception {
		client.removeBucket(RemoveBucketArgs.builder().bucket(hdfsProperties.getBucketName()).build());


	}


	public String getObjectURL(String objectName) throws Exception {
		GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder()
				.bucket(hdfsProperties.getBucketName())
				.object(objectName)  // 对象名称
				.build();

		return  client.getPresignedObjectUrl(args);
	}


//	public InputStream getObject(String objectName) throws Exception {
//		return client.getObject(GetObjectArgs.builder().bucket(hdfsProperties.getBucketName(),).object(objectName).build());
//
//	}


	public void putObject(String objectName, InputStream stream) throws Exception {
		Map<String, String> headers = new HashMap<String, String>();
		headers.put("Content-Type", "application/octet-stream");
		File file = new File(objectName);
		InputStream bais = new FileInputStream(file);
		client.putObject(
				PutObjectArgs.builder().bucket(hdfsProperties.getBucketName()).object(objectName).stream(
								bais, bais.available(), -1)
						.build());
	}


	public void putObject(String objectName, InputStream stream, String contextType) throws Exception {
		Map<String, String> headers = new HashMap<String, String>();
		headers.put("Content-Type", contextType);
		File file = new File(objectName);
		InputStream bais = new FileInputStream(file);
		client.putObject(
				PutObjectArgs.builder().bucket(hdfsProperties.getBucketName()).object(objectName).stream(
								bais, bais.available(), -1)
						.build());

	}


	public StatObjectResponse  getObjectInfo(String objectName) throws Exception {
		return client.statObject(
				StatObjectArgs.builder().bucket(hdfsProperties.getBucketName()).object(objectName).build());

	}


	public void removeObject(String objectName) throws Exception {
		client.removeObjects(
				RemoveObjectsArgs.builder().bucket(hdfsProperties.getBucketName()).build());
	}

}
